#include "CBattle.h"
#include "CMinionNode.h"
#include "COverlord.h"

CBattle::CBattle() : minionCount(0)
{
  //ctor
  std::cout << "CBattle started." << std::endl;
}

CBattle::~CBattle()
{
  vector<CMinionNode*>::iterator it;

  for ( it=vMinionDead.begin() ; it!=vMinionDead.end(); it++ )
  {
    (*it)->getNode()->remove();
    delete (*it);
  }

  for ( it=vMinion.begin() ; it!=vMinion.end(); it++ )
  {
    (*it)->getNode()->remove();
    delete (*it);
  }

  //dtor
  std::cout << "CBattle destroyed." << std::endl;
}

//! Methods to check for victory conditions
//! \return Player number of the winner. -1 for no winner
s32 CBattle::victoryCheck()
{
  // Currently there is only oen victory condition,
  // which is when one of the player lost all his minions
  u32 count;
  for ( u32 p=0; p<vPlayers.size(); p++ )
  {
    count = 0;
    for ( u32 m=0; m<vMinion.size(); m++ )
    {
      if ( vMinion[m]->getOwner() == vPlayers[p] )
        count++;
    }

    if ( count == 0 )
    {
      //! TODO: Fix this if players > 2;
      if ( p == 0 )
        return 1;
      else
        return 0;
    }
  }

  return -1;
}

void CBattle::castSpell()
{
  //! Overlord Spell
  /*
  //! TODO: Get spell data
  // spell data
  f32 value = 0.5f;
  COverlord *current = getFirstMinion()->getOwner();

  //! TODO: Make dynamic spell code (aka object/class declaratino for spell)

  list<CMinionNode*>::Iterator it;

  for ( it=vMinion.begin() ; it!=vMinion.end(); it++ )
  {
    CMinionNode *pMinion = (*it);
    if ( pMinion->getOwner() == current )
    {
      // Calculate restore amount
      f32 restore = f32 (pMinion->getMaxHp()) * value;
      s16 newHp = pMinion->getHp() + s16 (restore) ;

      // Prevents heal over max
      if ( newHp > pMinion->getMaxHp() )
        newHp = pMinion->getMaxHp();

      pMinion->setHp(newHp);


      stringw display( (s32) restore );
      IGUIFont *font = env->getFont("myfont.xml");
      vector3df startPos = pMinion->getNode()->getPosition();
      startPos.Y += 8;
      vector3df endPos = startPos;
      endPos.Y += 8;

      ITextSceneNode* numberDisplay = smgr->addTextSceneNode( font, display.c_str(), SColor(192, 0, 255, 0) );

      // Animator
      ISceneNodeAnimator* aim = smgr->createFlyStraightAnimator(startPos, endPos, 1000,  false);
      ISceneNodeAnimator* del = smgr->createDeleteAnimator(1000);

      numberDisplay->addAnimator(aim);
      numberDisplay->addAnimator(del);
    }
  }

  */
}


void CBattle::updateDelay(CMinionNode *target, u16 delay)
{
  CMinionNode *current, *next;
  u16 minus;

  // Set the new delay
  target->setDelay( target->getDelay() + delay );

  //! Sort the delay
  // Note that only one minion changed it's delay so all need to do is to
  // push down the "delayed" minion until it reach correct location

  // First we find the minion position
  u32 i;

  for ( i = 0; i < vMinion.size(); i++ )
  {
    if ( vMinion[i] == target )
      break;
  }

  // Start the loop from current position
  while ( i < vMinion.size()-1 )
  {
    current = vMinion[i];
    next = vMinion[i+1];

    // Stop when current minion delay is lower than next minion delay
    if ( current->getDelay() < next->getDelay() )
      break; // Break the loop

    else
    {
      // swap the value
      vMinion[i+1] = current;
      vMinion[i] = next;
    }

    i++;
  }

  //! Update the list so that the first minion delay is zero
  minus = vMinion.front()->getDelay();

  // No update needed
  if ( minus == 0 )
    return;

  for ( vector<CMinionNode*>::iterator it=vMinion.begin(); it!=vMinion.end(); it++ )
  {
    (*it)->setDelay( (*it)->getDelay() - minus );
  }
}



CMinionNode* CBattle::addMinion(CStateGame* state, minionStats& stats, u32 player)
{
  CMinionNode * pMinion = new CMinionNode(state, stats);
  vMinion.push_back(pMinion);
  pMinion->setID(minionCount);
  pMinion->setOwner(vPlayers[player]);
  minionCount++;
  return pMinion;
}

void CBattle::removeMinion(CMinionNode * minion)
{
  vector<CMinionNode*>::iterator it;

  for ( it=vMinion.begin() ; it!=vMinion.end(); it++ )
  {
    if ( (*it) == minion )
    {
      vMinionDead.push_back(*it);

      vMinion.erase(it);
      minion->getNode()->setVisible(false);
      return;
    }
  }
}

CMinionNode* CBattle::getMinion( ISceneNode * node )
{
  if ( node == 0 )
    return 0;

  for ( vector<CMinionNode*>::iterator it=vMinion.begin() ; it!=vMinion.end(); it++ )
    if ( node == (*it)->getNode() )
      return (*it);

  return 0;
}

CMinionNode * CBattle::getMinionFromID(u32 id)
{
  vector<CMinionNode*>::iterator it;

  for ( it=vMinion.begin() ; it!=vMinion.end(); it++ )
    if ( (*it)->getID() == id )
      return (*it);

  return 0;
}

COverlord * CBattle::getPlayer()
{
  return 0;
}

void CBattle::addPlayer(COverlord *player)
{
  vPlayers.push_back(player);
}

vector <CMinionNode*> & CBattle::getMinionList()
{
  return vMinion;
}

CMinionNode * CBattle::getFirstMinion()
{
  return * (vMinion.begin());
}
